package com.nana.petadventure.pe
{
	import com.nana.framework.base.App;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import org.cove.ape.APEVector;
	import org.cove.ape.APEngine;
	import org.cove.ape.AbstractParticle;
	import org.cove.ape.CollisionEvent;
	import org.cove.ape.RectangleParticle;
	
//	[SWF(width="960", height="640", backgroundColor="#000000")]
	public class PetEngine extends Sprite
	{
		private var cat:CatGroup;
		private var obstacleGroup:ObstacleGroup;
		private var distance:int = 0;
		private var _observerSpeed:Number;	// 观察者速度 用于计算相对速度
		private static var _instance:PetEngine;
		
		public function PetEngine()
		{
			super();
			_instance = this;
			if(this.stage) {
				this.init();
			} else {
				this.addEventListener(Event.ADDED_TO_STAGE, this.addedToStage);
			}
		}
		
		public static function getInstance():PetEngine {
			if(_instance == null)
				_instance = new PetEngine();
			return _instance;
		}
		
		public function get observerSpeed():Number
		{
			return _observerSpeed;
		}
		
		// 对小猫实体来说，他的速度为绝对速度；而对物理引擎来说，他的速度时相对速度
		public function set observerSpeed(value:Number):void
		{
			_observerSpeed = value;
			// 观察者速度改变时，必定要改变障碍物的相对速度。观察者速度其实就是小猫的速度
			obstacleGroup.observerSpeed = _observerSpeed;
		}
		
		private function addedToStage(event:Event):void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE, this.addedToStage);
			this.init();
		}
		
		public function init():void {
			stage.frameRate = App.appStage.frameRate;
			this.stage.addEventListener(Event.ENTER_FRAME,this.run);
			this.stage.addEventListener(MouseEvent.MOUSE_DOWN,mouseHandler);
			this.stage.addEventListener(MouseEvent.MOUSE_UP,mouseHandler);
			
			APEngine.init(0.25);	// 这里的参数是什么意思
			APEngine.container = this;
			//APEngine.addMasslessForce(new APEVector(0,3));	// 重力
			
			// TODO: 添加定时器 定时回收不显示的障碍物
			var timer:Timer = new Timer(3000);
			timer.addEventListener(TimerEvent.TIMER, onTimer);
			
			var wall:WallGroup = new WallGroup();
			APEngine.addGroup(wall);
			
			cat = new CatGroup();
			APEngine.addGroup(cat);
			cat.catBody.addEventListener(CollisionEvent.COLLIDE_RESOLVED, collisionHandler);
			obstacleGroup = new ObstacleGroup();
			APEngine.addGroup(obstacleGroup);
			
			cat.addCollidableList(new Array(wall,obstacleGroup));
			
			this.observerSpeed = cat.catSpeed;
			timer.start();
		}
		
		private function onTimer(event:TimerEvent):void {
			obstacleGroup.dismissObstacles();
		}
		
		private function run(event:Event):void {
			distance++;
			if (distance%50 == 0 && cat.status != Cat.STATUS_CRASH) {
				obstacleGroup.addObstacle();
			}
			cat.addGravity();
			if (cat.powered) {
				cat.addUpForce();
				
			}
			cat.printSpeed();

			// 这两步分别做了什么
			APEngine.step();
			APEngine.paint();
		}
		
		// 到达一定距离后难度增加
		private function speedUp():void {
			
		}
		
		private function mouseHandler(event:MouseEvent):void {
			if (event.type == MouseEvent.MOUSE_DOWN || event.type == MouseEvent.MOUSE_UP) {
				cat.toggleForce();
			}
			
		}
		
		
		// 撞击后的处理 统一在这里做 不在各自group内添加事件侦听
		public function collisionHandler(event:CollisionEvent):void {
			
			// 撞到障碍物GameOver
			if(event.collidingItem is ObstacleParticle) {
				// 移除点击事件的监听
				this.stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseHandler);
				this.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseHandler);
				// 处理被撞障碍物
				obstacleGroup.handleCrash(event.collidingItem as ObstacleParticle);
				
				// 撞击后的observerSpeed
				this.observerSpeed = cat.catSpeed - CatGroup.CRASH_HORIZONTAL_SPEED;
				// 小猫减速
				cat.removeCollidable(obstacleGroup);
				cat.handleCrash();
			} else if (event.collidingItem is RectangleParticle  && cat.status == Cat.STATUS_CRASH) {
				// TODO: crash后的observerSpeed
				
				this.observerSpeed = cat.catBody.velocity.x;
			}
			
		}
		
		public function pause():void {
			this.stage.removeEventListener(Event.ENTER_FRAME, this.run);
		}
		
		public function resume():void {
			this.stage.addEventListener(Event.ENTER_FRAME, this.run);
		}
		
	}
}